import { onUnmounted } from 'vue';
import deepcopy from 'deepcopy';
import { events } from '../../utils/events.js';

export const useCommands = (renderData, currentRenderDataIndex) => {
    const state = {
        current: -1,
        queue: [],
        commands: {},
        commandArray: [],
        destroyList: [],
    }

    const registry = (command) => {
        state.commandArray.push(command);
        state.commands[command.name] = (...args) => {
            const { forward, backoff } = command.execute(...args);
            forward()
            if(!command.isPushQueue) return;
            let { queue, current } = state;
            if(queue.length > 0) {
                queue = queue.slice(0, current + 1);
                state.queue = queue;
            }

            queue.push({ forward, backoff })
            state.current = current + 1
        }
    }

    registry({
        name: 'forward',
        isPushQueue: false,
        keyboard: 'ctrl+y',
        execute() {
            return {
                forward: () => {
                    let item = state.queue[state.current + 1]
                    if(item) {
                        item.forward && item.forward()
                        state.current++;
                    }
                }
            }
        }
    })

    registry({
        name: 'backoff',
        isPushQueue: false,
        keyboard: 'ctrl+z',
        execute() {
            return {
                forward: () => {
                    if(state.current == -1) return;
                    let item = state.queue[state.current];
                    if(item) {
                        item.backoff && item.backoff();
                        state.current--;
                    }
                }
            }
        }
    })

    registry({
        name: 'drag',
        isPushQueue: true,
        init() {
            this.before = null;
            const start = () => {
                // console.log('start')
                this.before = deepcopy(renderData.value)
            }
            const end = () => {
                // console.log('end')
                state.commands.drag();
            }
            events.on('start', start)
            events.on('end', end)

            return () => {
                events.off('start', start)
                events.off('end', end)
            }
        },
        execute() {
            const before = this.before;
            // const after = deepcopy(renderData.value);
            const after = renderData.value;
            return {
                forward: () => {
                    renderData.value = after;
                },
                backoff: () => {
                    renderData.value = before;
                }
            }
        }
    })

    registry({
        name: 'import',
        isPushQueue: true,
        execute(value) {
            const before = renderData.value;
            const after = value;
            return {
                forward: () => {
                    renderData.value = after;
                },
                backoff: () => {
                    renderData.value = before;
                }
            }
        },
    })

    registry({
        name: 'delete',
        isPushQueue: true,
        execute() {
            const before = deepcopy(renderData.value);
            renderData.value.splice(currentRenderDataIndex.value, 1);
            const after = deepcopy(renderData.value)
            return {
                forward: () => {
                    renderData.value = after;
                },
                backoff: () => {
                    renderData.value = before;
                }
            }
        }
    })

    const keyboardHandle = (() => {
        const keyCodes = { 90: 'z', 89: 'y', 46: 'delete' }
        const onKeyDown = (e) => {
            const { ctrlKey, keyCode } = e;
            let keyString = [];
            if(ctrlKey) keyString.push('ctrl');
            keyString.push(keyCodes[keyCode])
            keyString = keyString.join('+');

            state.commandArray.forEach(({keyboard, name}) => {
                if(!keyboard) return;
                if(keyboard == keyString) {
                    state.commands[name]();
                    e.preventDefault();
                }
            })
        }
        const init = () => {
            window.addEventListener('keydown', onKeyDown)
            return () => {
                window.removeEventListener('keydown', onKeyDown)
            }
        }
        return init
    })()

    ;(() => {
        state.destroyList.push(keyboardHandle())

        state.commandArray.forEach(command => {
            command.init && state.destroyList.push(command.init())
        })
    })()

    onUnmounted(() => {
        state.destroyList.forEach(fn => fn && fn())
    })

    return state
}